import re

from docutils.core import publish_parts

from pyramid.httpexceptions import HTTPFound, HTTPNotFound
from pyramid.url import route_url
from pyramid.security import authenticated_userid

from pycrowdsourcing.models import DBSession
from pycrowdsourcing.models import Page
from pycrowdsourcing.models import DataEntry

# regular expression used to find WikiWords
wikiwords = re.compile(r"\b([A-Z]\w+[A-Z]+\w+)")

class Literal(object):
    
    def __init__(self, string):
        self.s = string
    
    def __html__(self):
        return self.s

def getEntries():
    def getRow(cell_type, data, source):
        row  = "\n"
        row += "<tr>"
        row += "<" + cell_type + ">" + data + "</" + cell_type + ">"
        row += "<" + cell_type + ">" + source + "</" + cell_type + ">"
        row += "</tr>"
        row += "\n"
        return row
    
    html_body = "<table id=\"entries\" border=\"1\">"
    session = DBSession()
    entries = session.query(DataEntry).all()
    html_body += getRow("th", "DATA", "SOURCE")
    for entry in entries:
        html_body += getRow("td", entry.data, entry.source)
    html_body += "</table>"
    return Literal(html_body)

def view_wiki(request):
    return HTTPFound(location = route_url('view_page', request, pagename='FrontPage'))

def view_page(request):
    pagename = request.matchdict['pagename']
    session = DBSession()
    page = session.query(Page).filter_by(name=pagename).first()
    if page is None:
        return HTTPNotFound('No such page')

    def check(match):
        word = match.group(1)
        exists = session.query(Page).filter_by(name=word).all()
        if exists:
            view_url = route_url('view_page', request, pagename=word)
            return '<a href="%s">%s</a>' % (view_url, word)
        else:
            add_url = route_url('add_page', request, pagename=word)
            return '<a href="%s">%s</a>' % (add_url, word)

    content = publish_parts(page.data, writer_name='html')['html_body']
    content = wikiwords.sub(check, content)
    edit_url = route_url('edit_page', request, pagename=pagename)
    logged_in = authenticated_userid(request)
    data_entries = getEntries()
    return dict(page=page, content=content, logged_in=logged_in, 
                edit_url=edit_url, data_entries=data_entries)

def add_data(request):
    source = request.matchdict['source']
    if 'form.submitted' in request.params:
        session = DBSession()
        body = request.params['body']
        data = DataEntry(body, source)
        session.add(data)
        return HTTPFound(location = route_url('view_page', request, pagename='FrontPage'))
    
    save_url = route_url('add_data', request, source=source)
    entry = DataEntry('', '')
    logged_in = authenticated_userid(request)
    return dict(entry=entry, save_url=save_url, logged_in=logged_in)

def add_page(request):
    name = request.matchdict['pagename']
    if 'form.submitted' in request.params:
        session = DBSession()
        body = request.params['body']
        page = Page(name, body)
        session.add(page)
        return HTTPFound(location = route_url('view_page', request, pagename=name))

    save_url = route_url('add_page', request, pagename=name)
    page = Page('', '')
    logged_in = authenticated_userid(request)
    return dict(page=page, save_url=save_url, logged_in=logged_in,)

def edit_page(request):
    name = request.matchdict['pagename']
    session = DBSession()
    page = session.query(Page).filter_by(name=name).one()
    if 'form.submitted' in request.params:
        page.data = request.params['body']
        session.add(page)
        return HTTPFound(location = route_url('view_page', request, pagename=name))

    logged_in = authenticated_userid(request)
    return dict(page=page, save_url = route_url('edit_page', request, pagename=name), logged_in=logged_in,)
